package thread.blockingQueue;

import java.util.Random;

public class MyBlockingQueue {
    //通过循环队列的方式来实现
    private int[] elems = new int[1024];
    private volatile int size = 0;
    private int head = 0;
    private int tail = 0;

    public void put(int value) throws InterruptedException {
        synchronized (this) {
            //先判断put操作的时候 队列是否已经满了
            //注意使用while 而不是if 当线程再次被唤醒的时候，队列不一定就是没满
            while (size == elems.length){
                wait();
            }
            elems[tail] = value;
            tail = (tail + 1) % elems.length;
            size++;
            //成功插入一个新的元素后 就通知阻塞的take可以继续take了
            notifyAll();
        }
    }

    public int take() throws InterruptedException {
        int elem = 0;
        synchronized (this) {
            while(size == 0){
                wait();
            }
            elem = elems[head];
            head = (head + 1) % elems.length;
            size--;
            //成功拿走一个元素之后，就可以通知阻塞的put可以继续put了
            notifyAll();
        }
        return elem;
    }

    public synchronized int size() {
        return size;
    }

    // 测试代码
    public static void main(String[] args) throws InterruptedException {
        MyBlockingQueue blockingQueue = new MyBlockingQueue();
        Thread customer = new Thread(() -> {
            while (true) {
                try {
                    int value = blockingQueue.take();
                    System.out.println("消费："+ value);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "消费者");
        customer.start();
        Thread producer = new Thread(() -> {
            Random random = new Random();
            while (true) {
                try {
                    int nextInt = random.nextInt(10000);
                    System.out.println("生产：" + nextInt);
                    blockingQueue.put(nextInt);
                    //让生产者慢一点 观察消费者
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "生产者");
        producer.start();
        customer.join();
        producer.join();
    }

}
